package com.levi.threadpool;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author shentong
 * @since 2023/2/4 20:05
 * 异步线程池  配合@Async使用
 * @Async 失效的情况       https://blog.csdn.net/wang20010104/article/details/127337665
 * 1.注解@Async的方法不是public方法；
 * 2.注解@Async的返回值只能为void或Future；
 * 3.注解@Async方法使用static修饰也会失效；
 * 4.没加@EnableAsync注解；
 * 5.调用方和@Async不能在一个类中；
 * 6.在Async方法上标注@Transactional是没用的，但在Async方法调用的方法上标注@Transcational是有效的；
 */
@Configuration
@Slf4j
public class ThreadPoolConfig {


    @Bean(name = "myTaskExecutor")
    public ThreadPoolTaskExecutor myTaskExecutor() {
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        log.info("cpu核心数:{}", availableProcessors);
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程数
        executor.setCorePoolSize(availableProcessors);
        //核心线程数在空闲了keepAliveTime之后会被回收
        executor.setAllowCoreThreadTimeOut(true);
        //最大线程数
        executor.setMaxPoolSize(20);
        //活跃时间
        executor.setKeepAliveSeconds(60);
        //阻塞队列大小
        executor.setQueueCapacity(999);
        //线程池名称前缀
        executor.setThreadNamePrefix("taskExecutor - ");
        //设置此执行程序应该在关闭时阻止的最大秒数，以便在容器的其余部分继续关闭之前等待剩余的任务完成他们的执行
        executor.setAwaitTerminationSeconds(60);
        //等待所有的任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //setRejectedExecutionHandler：当pool已经达到max size的时候，如何处理新任务
        //CallerRunsPolicy：不在新线程中执行任务，而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;
    }
}
